package com.topisv.tms.service.shipped;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.hibernate.ejb.criteria.predicate.ComparisonPredicate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.persistence.DynamicSpecifications;
import org.springside.modules.persistence.SearchFilter;
import org.springside.modules.persistence.SearchFilter.Operator;

import com.topisv.tms.entity.BackupTaskOrdeno;
import com.topisv.tms.entity.Customers;
import com.topisv.tms.entity.EdiOrder;
import com.topisv.tms.entity.EdiOrderItem;
import com.topisv.tms.entity.ShippedBatch;
import com.topisv.tms.entity.ShippedBox;
import com.topisv.tms.entity.ShippedBoxOrdeno;
import com.topisv.tms.entity.ShippedBoxSkus;
import com.topisv.tms.entity.User;
import com.topisv.tms.entity.log.OrderLog;
import com.topisv.tms.repository.BackupTaskOrdenoDao;
import com.topisv.tms.repository.CustomersDao;
import com.topisv.tms.repository.EdiOrderDao;
import com.topisv.tms.repository.EdiOrderItemDao;
import com.topisv.tms.repository.ShippedBatchDao;
import com.topisv.tms.repository.ShippedBoxDao;
import com.topisv.tms.repository.ShippedBoxOrdenoDao;
import com.topisv.tms.repository.ShippedBoxSkusDao;
import com.topisv.tms.repository.UserDao;
import com.topisv.tms.repository.log.OrderLogDao;
import com.topisv.tms.rest.entity.Batch;
import com.topisv.tms.rest.entity.Box;
import com.topisv.tms.rest.entity.Box_detail;
import com.topisv.tms.rest.entity.Order;
import com.topisv.tms.rest.entity.forward.ForwardBatch;
import com.topisv.tms.rest.entity.forward.ForwardBox;
import com.topisv.tms.rest.entity.forward.ForwardOrdeno;
import com.topisv.tms.rest.entity.forward.ForwardOrdenoItem;
import com.topisv.tms.utils.TimeUtil;

@Component
@Transactional(readOnly = true)
public class ShippedBatchService {
	@Autowired
	private ShippedBatchDao shippedBatchDao;
	@Autowired
	private ShippedBoxSkusDao shippedBoxSkusDao;
	@Autowired
	private ShippedBoxDao shippedBoxDao;
	@Autowired
	private BackupTaskOrdenoDao backupTaskOrdenoDao;
	@Autowired
	private EdiOrderDao ediOrderDao;
	@Autowired
	private EdiOrderItemDao ediOrderItemDao;
	@Autowired
	private ShippedBoxOrdenoDao shippedBoxOrdenoDao;
	@Autowired
	private CustomersDao customersDao;
	@Autowired
	private OrderLogDao orderLogDao;

	
	@Transactional(readOnly = false)
	public void saveSendBatchOrderLog(String batchCode){
		List<BackupTaskOrdeno> btos=this.backupTaskOrdenoDao.findByBatchCode(batchCode);
		ShippedBatch shippedBatch=shippedBatchDao.findByBackupTaskCode(batchCode);
		shippedBatch.setStatus("finish");
		shippedBatchDao.save(shippedBatch);
		Date nowDate=new Date();
		for(BackupTaskOrdeno b:btos){
			OrderLog log=new OrderLog(
					b.getOrdeno(),
					shippedBatch.getCustomerCode(),
					"3", //操作类型 （1.创建批次 2.创建任务  3.拣货完成 4.包装完成 5.发货完成 6.签收完成 7.异常登记 8.完成灯光拣选任务 9.打印单据）
					null,
					nowDate,
					null,
					"出库批次推送成功");
			this.orderLogDao.save(log);
		}
	}
	
	
	
	public ShippedBatch findByBackupTaskCode(String backupTaskCode){
		return shippedBatchDao.findByBackupTaskCode(backupTaskCode);
	}
	
	/**
	 * 分页显示表内所有行.
	 */
	public Page<ShippedBatch> getPageShippedBatchs(Map<String, Object> filterParams,
			int pageNumber, int pageSize, String sortType) {
		PageRequest pageRequest = buildPageRequest(pageNumber, pageSize,sortType);
		Specification<ShippedBatch> spec = buildSpecification(filterParams);
		return shippedBatchDao.findAll(spec, pageRequest);
	}
	
	 public Page<ShippedBatch> findShippedBatchStatus(int pageNumber, int pageSize,String sortType,final Map<String, Object> param) {
		    PageRequest pageRequest=buildPageRequest(pageNumber, pageSize, sortType);
			Specification<ShippedBatch> spec = buildSpecificationNew(param);
			return shippedBatchDao.findAll(spec, pageRequest);
		}
		
		public List<ShippedBatch> findShippedBatchStatus(final Map<String, Object> param) {
			
			Specification<ShippedBatch> spec = buildSpecificationNew(param);
			return shippedBatchDao.findAll(spec);
		}

		private Specification<ShippedBatch> buildSpecificationNew(final Map<String, Object> param) {return new Specification<ShippedBatch>() {
				@Override
				public Predicate toPredicate(Root<ShippedBatch> r,CriteriaQuery<?> q, CriteriaBuilder cb) {

					Predicate pre = cb.conjunction();
					String customers=(String)param.get("customers");//商家编码列表
					
					if (StringUtils.isNotBlank(customers)) {
						String[] customerLists = customers.split(":");
						ComparisonPredicate[] tempCustomerCode = new ComparisonPredicate[customerLists.length];
						int i = 0;
						for (String customer : customerLists) {
							tempCustomerCode[i] = (ComparisonPredicate) cb.equal(r.get("customerCode"), customer);
							i++;
						}
						pre.getExpressions().add(cb.or(tempCustomerCode));
					}

					String areagroups=(String)param.get("areagroups");//网点列表
					if (StringUtils.isNotBlank(areagroups)) {
						String[] areagroupLists = areagroups.split(":");
						ComparisonPredicate[] tempCustomerCode = new ComparisonPredicate[areagroupLists.length];
						int i = 0;
						for (String areagroup : areagroupLists) {
							tempCustomerCode[i] = (ComparisonPredicate) cb.equal(r.get("areaGroupCode"), areagroup);
							i++;
						}
						pre.getExpressions().add(cb.or(tempCustomerCode));
					}

					String status=(String)param.get("status");//装箱状态
					if (StringUtils.isNotBlank(status)) {
						pre.getExpressions().add(cb.equal(r.get("status"), status));
					}
					String batchType=(String)param.get("batchType");
					if (StringUtils.isNotBlank(batchType)) {
						pre.getExpressions().add(cb.equal(r.get("type"), batchType));
					}
					
					
					String jobuuids=(String)param.get("jobuuid");//任务领取状态
					if (StringUtils.isNotBlank(jobuuids)) {
						String[] jobuuid = jobuuids.split(":");
						ComparisonPredicate[] tempJobuuid = new ComparisonPredicate[jobuuid.length];
						int i = 0;
						for (String pt : jobuuid) {
							tempJobuuid[i] = (ComparisonPredicate) cb.equal(r.get("jobuuid"), pt);
							i++;
						}
						pre.getExpressions().add(cb.or(tempJobuuid));
					}
					
					
					
					 Date fromDate= (Date) param.get("fromDate");
				      if (fromDate != null) {
				        pre.getExpressions().add(cb.greaterThanOrEqualTo(r.<Date>get("createDate"), fromDate));
				      }
				      
				      Date toDate= (Date) param.get("toDate");
				      if (toDate != null) {
				        pre.getExpressions().add(cb.lessThanOrEqualTo(r.<Date>get("createDate"), toDate));
				      }
				      
				      String warehouseCode=(String) param.get("warehouseCode");
				      if (StringUtils.isNotBlank(warehouseCode)) {
							String[] warehouseCodeLists = warehouseCode.split(":");
							ComparisonPredicate[] tempCustomerCode = new ComparisonPredicate[warehouseCodeLists.length];
							int i = 0;
							for (String wc : warehouseCodeLists) {
								tempCustomerCode[i] = (ComparisonPredicate) cb.equal(r.get("warehouseCode"), wc);
								i++;
							}
							pre.getExpressions().add(cb.or(tempCustomerCode));
						}
				      
				 

					return pre;
				}

			};
		}
	
	/**
	 * 分页显示表内所有行.
	 */
	public List<ShippedBatch> getListShippedBatchs(Map<String, Object> filterParams) {
		
		Specification<ShippedBatch> spec = buildSpecification(filterParams);
		return shippedBatchDao.findAll(spec);
	}

	/**
	 * 分页显示表内所有行.
	 */
	public Page<ShippedBatch> getPageShippedBatchs(Map<String, Object> filterParams,int pageNumber, int pageSize, String sortType, Date fromDate,Date endDate) {
		PageRequest pageRequest = buildPageRequest(pageNumber, pageSize,sortType);
		Specification<ShippedBatch> spec = buildSpecification(filterParams,fromDate, endDate);
		return shippedBatchDao.findAll(spec, pageRequest);
	}
	
	public Page<ShippedBatch> getPageShippedBatchs(int pageNumber, int pageSize, String sortType, Date fromDate,Date endDate,String type,String username,String customers,String areagroups) {
		PageRequest pageRequest = buildPageRequest(pageNumber, pageSize,sortType);
		Specification<ShippedBatch> spec = buildSpecification(fromDate, endDate,type,username,customers,areagroups);
		return shippedBatchDao.findAll(spec, pageRequest);
	}
	
	private Specification<ShippedBatch> buildSpecification(final Date fromDate,final Date endDate,final String type,final String username,final String customers,final String areagroups) {
		return new Specification<ShippedBatch>(){
			@Override
			public Predicate toPredicate(Root<ShippedBatch> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
				
				Predicate pre = cb.conjunction();
				if(StringUtils.isNotBlank(customers)){
					String[] customerLists=customers.split(":");
					ComparisonPredicate[]  tempCustomerCode=new ComparisonPredicate[customerLists.length];
					int i=0;
					for(String customer:customerLists){
						tempCustomerCode[i]=(ComparisonPredicate) cb.equal(r.get("customerCode"), customer);
						i++;
					}
					pre.getExpressions().add(cb.or(tempCustomerCode));
				}
				
				if(StringUtils.isNotBlank(areagroups)){
					String[] areagroupLists=areagroups.split(":");
					ComparisonPredicate[]  tempCustomerCode=new ComparisonPredicate[areagroupLists.length];
					int i=0;
					for(String areagroup:areagroupLists){
						tempCustomerCode[i]=(ComparisonPredicate) cb.equal(r.get("areaGroupCode"), areagroup);
						i++;
					}
					pre.getExpressions().add(cb.or(tempCustomerCode));
				}
				
				
				if(fromDate!=null){
					pre.getExpressions().add(cb.greaterThan(r.<Date>get("createDate"), fromDate));
				}
				
				if(endDate!=null){
					pre.getExpressions().add(cb.lessThan(r.<Date>get("createDate"), endDate));
				}
				
				if(StringUtils.isNotBlank(username)){
					pre.getExpressions().add(cb.like(r.<String>get("username"), username));

				}
				
				if(StringUtils.isNotBlank(type)){
					pre.getExpressions().add(cb.equal(r.get("type"), type));

				}

				return pre;
			}
			
		};
	}

	/**
	 * 创建分页请求.
	 */
	private PageRequest buildPageRequest(int pageNumber, int pageSize,
			String sortType) {
		Sort sort = null;
		if (null != sortType) {
			if (sortType.endsWith("desc")) {
				sort = new Sort(Direction.DESC, "id");
			} else if (sortType.endsWith("asc")) {
				sort = new Sort(Direction.ASC, "id");
			}
		}
		return new PageRequest(pageNumber - 1, pageSize, sort);
	}

	private Specification<ShippedBatch> buildSpecification(Map<String, Object> filterParams, Date fromDate, Date endDate) {
		Map<String, SearchFilter> filters = SearchFilter.parse(filterParams);
		filters.put("fromDate", new SearchFilter("createDate", Operator.GTE,fromDate));
		filters.put("toDate", new SearchFilter("createDate", Operator.LT,endDate));
		Specification<ShippedBatch> spec = DynamicSpecifications.bySearchFilter(filters.values(), ShippedBatch.class);
		return spec;
	}

	/**
	 * 创建动态查询条件组合.
	 */
	private Specification<ShippedBatch> buildSpecification(Map<String, Object> filterParams) {
		Map<String, SearchFilter> filters = SearchFilter.parse(filterParams);
		Specification<ShippedBatch> spec = DynamicSpecifications.bySearchFilter(filters.values(), ShippedBatch.class);
		return spec;
	}
	
	public List<ShippedBatch> findByStatusAndJobuuid(String status,String jobuuid){
		return shippedBatchDao.findByStatusAndJobuuid(status, jobuuid);
	}
	
	public List<ShippedBatch> findByStatus(String status){
		return shippedBatchDao.findByStatus(status);
	}
	
	public List<ShippedBatch> findByStatusAndCustomerCode(String status,String customerCode){
		return shippedBatchDao.findByStatusAndCustomerCode(status, customerCode);
	}
	
	public List<ShippedBatch> findShippedBatchStatus(final String customers,final String areagroups,final String status) {
	
		Specification<ShippedBatch> spec = buildSpecification(customers,areagroups, status);
		return shippedBatchDao.findAll(spec);
	} 
	
	private Specification<ShippedBatch> buildSpecification(final String customers,final String areagroups,final String status) {
		return new Specification<ShippedBatch>(){
			@Override
			public Predicate toPredicate(Root<ShippedBatch> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
				
				Predicate pre = cb.conjunction();
				if(StringUtils.isNotBlank(customers)){
					String[] customerLists=customers.split(":");
					ComparisonPredicate[]  tempCustomerCode=new ComparisonPredicate[customerLists.length];
					int i=0;
					for(String customer:customerLists){
						tempCustomerCode[i]=(ComparisonPredicate) cb.equal(r.get("customerCode"), customer);
						i++;
					}
					pre.getExpressions().add(cb.or(tempCustomerCode));
				}
				
				if(StringUtils.isNotBlank(areagroups)){
					String[] areagroupLists=areagroups.split(":");
					ComparisonPredicate[]  tempCustomerCode=new ComparisonPredicate[areagroupLists.length];
					int i=0;
					for(String areagroup:areagroupLists){
						tempCustomerCode[i]=(ComparisonPredicate) cb.equal(r.get("areaGroupCode"), areagroup);
						i++;
					}
					pre.getExpressions().add(cb.or(tempCustomerCode));
				}
				
				if(StringUtils.isNotBlank(status)){
					pre.getExpressions().add(cb.equal(r.get("status"), status));
				}
				
				
				return pre;
			}
			
		};
	}

	public ShippedBatch findByBatchCode(String batchCode) {
		return shippedBatchDao.findByBatchCode(batchCode);
	}

	public List<ShippedBatch> findByCreateDateBetween(Date startDate,
			Date endDate) {
		return shippedBatchDao.findByCreateDateBetween(startDate, endDate);
	}

	@Transactional(readOnly = false)
	public ShippedBatch save(ShippedBatch arg0) {
		return shippedBatchDao.save(arg0);
	}

	@Transactional(readOnly = false)
	public List<ShippedBatch> save(List<ShippedBatch> arg0) {
		return (List<ShippedBatch>) shippedBatchDao.save(arg0);
	}

	/**
	 * 生成出库批次信息
	 * @param batchCode
	 * @param customerCode
	 * @return
	 * @throws Exception 
	 */
	public Batch getBatch(String batchCode,String customerCode) throws Exception {
		try {
			ShippedBatch shippedBatch=shippedBatchDao.findByBatchCode(batchCode);
			List<ShippedBoxSkus> tempShippedBoxSkus=shippedBoxSkusDao.findByBoxCodeAndBatchCode(null, shippedBatch.getBatchCode());
			if(!tempShippedBoxSkus.isEmpty()){//判断时候封箱
				return null;
			}
			if("forward".equals(shippedBatch.getType())){
				throw new Exception("该出库批次编号类型:"+shippedBatch.getType());
			}
			Date nowDate=new Date();
			Batch batch = new Batch();
			List<Box> boxs=new ArrayList<Box>();
			List<Order> orders=new ArrayList<Order>();
			batch.setBatch(shippedBatch.getBatchCode());
			batch.setCustomer_code(customerCode);
			batch.setGoods_num(shippedBatch.getSkuQty());
			batch.setOrder_num(shippedBatch.getOrdenoQty());
			batch.setStartpoints("010");
			batch.setShipped_time(TimeUtil.getNowDateString(shippedBatch.getCreateDate()));
			batch.setBox(boxs);
			batch.setOrder(orders);
			batch.setType(shippedBatch.getType());
			batch.setBox_num(shippedBatch.getBoxQty());//箱子格式
			List<ShippedBox>  shippedBoxs=shippedBoxDao.findByBatchCode(shippedBatch.getBatchCode());
			//设置出库批次的箱子商品信息
			for(ShippedBox shippedBox:shippedBoxs ){
				List<Box_detail> box_details=new ArrayList<Box_detail>();;
				Box box=new Box();
				String boxCode=shippedBox.getBoxCode();
				box.setBox_code(boxCode);
				box.setBox_type(shippedBox.getType());
	            box.setGoods_num(shippedBox.getSkuQty());
	            box.setBox_detail(box_details);
				List<ShippedBoxSkus> shippedBoxSkus=shippedBoxSkusDao.findByBoxCode(boxCode);
				for(ShippedBoxSkus obj:shippedBoxSkus){
					Box_detail box_detail=new Box_detail();
					box_detail.setBox(obj.getBoxCode());
					box_detail.setNum(obj.getRealQty());
					box_detail.setSku(obj.getSkuId());
					box_details.add(box_detail);
				}
				
				boxs.add(box);
			}
			//设置出库批次的订单信息
			List<BackupTaskOrdeno> backupTaskOrdenos=backupTaskOrdenoDao.findByBackupTaskCode(shippedBatch.getBackupTaskCode());
			for(BackupTaskOrdeno obj:backupTaskOrdenos){
				Order order=new Order();
				String ordeno=obj.getOrdeno();
				EdiOrder ediOrder=ediOrderDao.findByOrdeno(ordeno);
				order.setOrdeno(ordeno);
				order.setFromno(ediOrder.getFromno());
				order.setOrder_type(ediOrder.getOrderType());
				order.setSku_num(ediOrder.getSkuQty());
				orders.add(order);
				
				OrderLog log=new OrderLog(
						obj.getOrdeno(),
						shippedBatch.getCustomerCode(),
						"3", //操作类型 （1.创建批次 2.创建任务  3.拣货完成 4.包装完成 5.发货完成 6.签收完成 7.异常登记 8.完成灯光拣选任务 9.打印单据）
						null,
						nowDate,
						null,
						"开始推送出库批次");
				this.orderLogDao.save(log);
			}
			batch.setEndpoints(shippedBatch.getAreaGroupCode());
			return batch;
		} catch (Exception e) {
			throw e;
		}
	}
	
	/**
	 * 生成出库批次信息
	 * @param backupTaskCode
	 * @param customerCode
	 * @return
	 */
	public ForwardBatch getForwardBatch(String batchCode,String customerCode) throws Exception{
		try {
			ShippedBatch shippedBatch=shippedBatchDao.findByBatchCode(batchCode);
			Customers customers=customersDao.findByCustomerCode(customerCode);
			if(!"forward".equals(shippedBatch.getType())){
				throw new Exception("该出库批次编号类型:"+shippedBatch.getType());
			}
			
			ForwardBatch forwardBatch=new ForwardBatch();
			int orderNum=0;
			int goodsNum=0;
			List<ForwardBox> forwardBoxs=new ArrayList<ForwardBox>();
			forwardBatch.setForwardBoxs(forwardBoxs);
			forwardBatch.setBatch(batchCode);
			forwardBatch.setCustomerCode(customerCode);
			forwardBatch.setEndpoints(shippedBatch.getAreaGroupCode());
		   
			forwardBatch.setType(shippedBatch.getType());
			forwardBatch.setStartpoints(customers.getStartPoint());
			List<ShippedBox> shippedBoxs=shippedBoxDao.findByBatchCode(shippedBatch.getBatchCode());
		    for(ShippedBox shippedBox:shippedBoxs){
		    	ForwardBox forwardBox=new ForwardBox();
		    	forwardBoxs.add(forwardBox);
		    	forwardBox.setBoxCode(shippedBox.getBoxCode());
		    	List<ShippedBoxOrdeno> shippedBoxOrdenos=shippedBoxOrdenoDao.findByBoxCode(shippedBox.getBoxCode());
		    	List<ForwardOrdeno> forwardOrdenos=new ArrayList<ForwardOrdeno>();
		    	forwardBox.setForwardOrdeno(forwardOrdenos);
		    	
		    	for(ShippedBoxOrdeno shippedBoxOrdeno:shippedBoxOrdenos){
		    		orderNum++;
		    		ForwardOrdeno forwardOrdeno=new ForwardOrdeno();
		    		forwardOrdenos.add(forwardOrdeno);
		    		List<ForwardOrdenoItem> forwardOrdenoItems=new ArrayList<ForwardOrdenoItem>();
		    		forwardOrdeno.setForwardOrdenoItems(forwardOrdenoItems);
		    		EdiOrder e=ediOrderDao.findByOrdeno(shippedBoxOrdeno.getOrdeno());
		    		forwardOrdeno.setOrdeno(e.getOrdeno());
		    		forwardOrdeno.setReceiverAddress(e.getAddres());
		    		forwardOrdeno.setReceiverCity(e.getCityna());
		    		forwardOrdeno.setReceiverDistrict(e.getDistna());
		    		forwardOrdeno.setReceiverMobile(e.getMobile());
		    		forwardOrdeno.setReceiverName(e.getRecena());
		    		forwardOrdeno.setReceiverPhone(e.getTeleph());
		    		forwardOrdeno.setReceiverState(e.getProvna());
		    		forwardOrdeno.setSememo(e.getSememo());
		    		forwardOrdeno.setShopName(e.getShopna());
		    		forwardOrdeno.setTotalPrice(e.getActuallyPaid());
		    		forwardOrdeno.setWaybillNo(e.getWaybillNo());
		    		forwardOrdeno.setReceiverProvco(e.getProvco());
		    		
		    		List<EdiOrderItem> ediOrderItems=ediOrderItemDao.findByOrdeno(shippedBoxOrdeno.getOrdeno());
		    		for(EdiOrderItem eio:ediOrderItems){
		    			goodsNum+=eio.getQty();
		    			ForwardOrdenoItem fi=new ForwardOrdenoItem();
		    			forwardOrdenoItems.add(fi);
		    			fi.setSkuId(eio.getSku());
		    			fi.setPrice(eio.getPri());
		    			fi.setQty(eio.getQty());
		    			fi.setSiz(eio.getSiz());
		    			fi.setProperties(fi.getProperties());
		    		}
		    	}
		    }
			forwardBatch.setBoxNum(forwardBoxs.size());
			forwardBatch.setOrderNum(orderNum);
			forwardBatch.setGoodsNum(goodsNum);
			return forwardBatch;
		} catch (Exception e) {
			throw e;
		}
	}
}
